const { model } = require("../models/note");
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const mongoose = require('mongoose');
const {
    AuthenticationError,
    ForbiddenError
} = require('apollo-server-express');
require('dotenv').config();

const gravatar = require("../util/gravatar");

module.exports = {
    newNote: async (parent, args, { models, user }) => {
        if (!user) {
            throw new AuthenticationError('You must be signed in to creat a note');
        }

        return await models.Note.create ({
            content: args.content,
            author: mongoose.Types.ObjectId(user.id)
        });
    },
    
    deleteNote: async (parent, { id }, { models, user }) => {
        if (!user) {
            throw new AuthenticationError('You must be signed in to delete a note');
        }

        const note = await models.Note.findById(id);
        if (note && String(note.author) !== user.id) {
            throw new ForbiddenError("You don't have permission to delete the note");
        }

        try{
            //通过所有检查后删除笔记
            await note.remove();
            return true;
        }catch(err){
            return false;
        }
    },

    updateNote: async (parent, { content,id }, { models, user }) => {
        if (!user) {
            throw new AuthenticationError('You must be signed in to update a note');
        }

        const note = await models.Note.findById(id);
        if (note && String(note.author) !== user.id) {
            throw new ForbiddenError("You don't have permission to update the note");
        }

        //更新数据库中的笔记，返回更新后的笔记
        return await models.Note.findOneAndUpdate(
            {
                _id: id,
            },
            {
                $set: {
                    content
                }
            },
            {
                new: true
            }
        )
    },
    
    signUp: async (parent, {username, email, password}, { models }) => {
        //规范邮件地址
        email = email.trim().toLowerCase();
        //计算密码的哈希值
        const hashed = await bcrypt.hash(password, 10);
        //生成Gravatar URL
        const avatar = gravatar(email);
        try{
            const user = await models.User.create({
                username,
                email,
                avatar,
                password: hashed
            });
            return jwt.sign({id: user._id }, process.env.JWT_SECRET);
        }catch(err){
            console.log(err);
            throw new Error('Error creating account');
        }
    },

    signIn: async (parent, { username, email, password }, { models }) => {
        if (email) {
            //规范邮箱格式
            email = email.trim().toLowerCase();
        }
    
        const user = await models.User.findOne({
            $or: [{ email }, { username }]
        });
    
        if (!user) {
          throw new AuthenticationError('Error signing in');
        }
    
        const valid = await bcrypt.compare(password, user.password);
        if (!valid) {
          throw new AuthenticationError('Error signing in');
        }
    
        return jwt.sign({ id: user._id }, process.env.JWT_SECRET);
    },
    
    toggleFavorite: async (parent, { id }, { models, user }) => {
        if (!user) {
            throw new AuthenticationError();
        }

        //检查用户是否语句收藏了该笔记
        let noteCheck = await models.Note.findById(id);
        const hasUser = noteCheck.favoritedBy.indexOf(user.id);

        //如果当前用户在列表中
        //把用户从列表中删除，并减少对应的值`favoriteCount`的值减少一个
        if (hasUser >= 0) {
            return await models.Note.findByIdAndUpdate(
                id,
                {
                    $pull: {
                        favoritedBy: mongoose.Types.ObjectId(user.id)
                    },
                    $inc: {
                        favoriteCount: -1
                    }
                },
                {
                    new: true
                }
            );
        }else{
            //如果当前用户不在列表中
            //把用户添加到列表中，并把`favoriteCount`的值增加一个
            return await models.Note.findByIdAndUpdate(
                id,
                {
                    $push: {
                        favoritedBy: mongoose.Types.ObjectId(user.id)
                    },
                    $inc: {
                        favoriteCount: 1
                    }
                },
                {
                    new: true
                }
            )
        }
    }
}